<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>flexbox布局笔记</title>
  <link rel="icon" type="image/png" href="../think/assets/ant.png">
  <link href="../styles.css" rel="stylesheet">
  <link href="../vs.css" rel="stylesheet">
  <!-- Global site tag (gtag.js) - Google Analytics -->
  <script async src="https://www.googletagmanager.com/gtag/js?id=UA-131906119-1"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());

    gtag('config', 'UA-131906119-1');
  </script>
  <script async src="../index.js"></script>
</head>
<body>
<h1>flexbox布局笔记</h1>
<p>flexbox布局涉及两个元素，一个是<strong>容器</strong>，一个是容器中的<strong>子项</strong>。flexbox的css属性，一部分设置在容器上，一部分设置在子项上。不管在哪个上面设置，影响的都是子项的排列方式和大小。在容器上设置影响所有的子项，在某个子项上设置则只影响该子项。</p>
<p>注：为了说明方便，以下示例均假设了主轴方向为水平从左往右，因此交叉轴方向为垂直从上往下。</p>
<h2>作用于容器上的属性</h2>
<ul>
<li><code>flex-direction</code>：设置主轴的方向，即子项的排列方向
<ul>
<li>row：默认值。水平从左往右方向</li>
<li>row-reverse：水平从右往左</li>
<li>column：垂直从上往下。React-Native中该值为默认值</li>
<li>column-reverse：垂直从下往上</li>
</ul>
</li>
<li><code>flex-wrap</code>：超过容器时是否折行
<ul>
<li>wrap：默认值。折行</li>
<li>nowrap：不折行</li>
</ul>
</li>
<li><code>flex-flow</code>：<code>flex-direction</code>和<code>flex-wrap</code>合并写法</li>
<li><code>justify-content</code>：主轴方向子项排列的方式（下面的值以水平从左往右为例）
<ul>
<li>flex-start：默认值。居右排列，子项间没有空白<div class="container justify-content-flex-start">
  <div class="item">子项1</div>
  <div class="item">子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>flex-end：居左排列<div class="container justify-content-flex-end">
  <div class="item">子项1</div>
  <div class="item">子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>center：居中排列<div class="container justify-content-center">
  <div class="item">子项1</div>
  <div class="item">子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>space-around：给每个子项左右分配同等多余空白空间，且相邻子项间的空间不重叠<div class="container justify-content-space-around">
  <div class="item">子项1</div>
  <div class="item">子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>space-between：将多余空间均匀分配在子项之间<div class="container justify-content-space-between">
  <div class="item">子项1</div>
  <div class="item">子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>space-evenly：将多余空间均匀分配在子项之间以及容器的首尾处<div class="container justify-content-space-evenly">
  <div class="item">子项1</div>
  <div class="item">子项2</div>
  <div class="item">子项3</div>
</div>
</li>
</ul>
</li>
<li><code>align-items</code>：每行子项垂直方向对齐方式
<ul>
<li>stretch：默认值。拉伸子项至容器高度<div class="container align-items-stretch">
  <div class="item">子项1<br>子项1</div>
  <div class="item">子项2<br>子项2<br>子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>flex-start：与容器顶部对齐<div class="container align-items-flex-start">
  <div class="item">子项1<br>子项1</div>
  <div class="item">子项2<br>子项2<br>子项2</div>
  <div class="item">子项3</div>
</div>
</div>
</li>
<li>flex-end：与容器底部对齐<div class="container align-items-flex-end">
  <div class="item">子项1<br>子项1</div>
  <div class="item">子项2<br>子项2<br>子项2</div>
  <div class="item">子项3</div>
</div>
</div>
</li>
<li>center：垂直方向居中<div class="container align-items-center">
  <div class="item">子项1<br>子项1</div>
  <div class="item">子项2<br>子项2<br>子项2</div>
  <div class="item">子项3</div>
</div>
</div>
</li>
</ul>
</li>
<li><code>align-centent</code>：类似<code>justify-content</code>，表示多行的情况下子项在垂直方向上的排列方式
<ul>
<li>stretch：每行子项平分高度<div class="container align-content-stretch flex-wrap-wrap" style="width: 120px; height: 200px;">
  <div class="item" style="width: 100px;">子项1<br>子项1</div>
  <div class="item">子项2<br>子项2<br>子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>flex-start<div class="container align-content-flex-start flex-wrap-wrap" style="width: 120px; height: 200px;">
  <div class="item" style="width: 100px;">子项1<br>子项1</div>
  <div class="item">子项2<br>子项2<br>子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>flex-end<div class="container align-content-flex-end flex-wrap-wrap" style="width: 120px; height: 200px;">
  <div class="item" style="width: 100px;">子项1<br>子项1</div>
  <div class="item">子项2<br>子项2<br>子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>center<div class="container align-content-center flex-wrap-wrap" style="width: 120px; height: 200px;">
  <div class="item" style="width: 100px;">子项1<br>子项1</div>
  <div class="item">子项2<br>子项2<br>子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>space-between<div class="container align-content-space-between flex-wrap-wrap" style="width: 120px; height: 200px;">
  <div class="item" style="width: 100px;">子项1<br>子项1</div>
  <div class="item">子项2<br>子项2<br>子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>space-around<div class="container align-content-space-around flex-wrap-wrap" style="width: 120px; height: 200px;">
  <div class="item" style="width: 100px;">子项1<br>子项1</div>
  <div class="item">子项2<br>子项2<br>子项2</div>
  <div class="item">子项3</div>
</div>
</li>
<li>space-evenly<div class="container align-content-space-evenly flex-wrap-wrap" style="width: 120px; height: 200px;">
  <div class="item" style="width: 100px;">子项1<br>子项1</div>
  <div class="item">子项2<br>子项2<br>子项2</div>
  <div class="item">子项3</div>
</div>
</li>
</ul>
</li>
</ul>
<h2>作用于子项上的属性</h2>
<ul>
<li><code>flex-grow</code>：子项的放大值，默认值为0，不放大，接受非负整数和小数。决定了每个子项如何分配多余空间。当子项的放大值之和大于等于1时，会将多余空间刚好消耗，每个子项分配的空间为多余空间乘以该子项放大值在放大值之和的占比；放大值之和小于1时，则消耗的空间为多余空间乘以放大值之和，每个子项分配多余空间乘以该子项的放大值。
<ul>
<li>放大值为2、3、5的情况：下面示例中容器的宽度为300px，子项1为80px，子项2为70px，子项3为50px，所欲有100px的多余空间。因为放大值之和2+3+5=10大于等于1，所以子项1宽度增加100px*2/10=20px，子项2宽度增加100px*3/10=30px，子项3宽度增加100px*5/10=50px，最终每个子项的宽度都变为了100px。<div class="container flex-wrap-nowrap" style="width: 300px; height: 50px;">
    <div class="item flex-grow-2" style="width: 80px;">子项1</div>
    <div class="item flex-grow-3" style="width: 70px;">子项2</div>
    <div class="item flex-grow-5" style="width: 50px;">子项3</div>
  </div>
</li>
<li>放大值为0.1、0.2、0.4的情况：下面的示例中容器宽度为300px，子项1为80px，子项2为70px，子项3为50px，多余空间为100px。因为放大值之和0.1+0.2+0.4=0.7小于1，所以子项1增加100px*0.1=10px，子项2增加100px*0.2=20px，子项3增加100px*0.4=40px，最终每个子项的宽为90px，还剩30px多余空间。<div class="container flex-wrap-nowrap" style="width: 300px; height: 50px;">
    <div class="item flex-grow-01" style="width: 80px;">子项1</div>
    <div class="item flex-grow-02" style="width: 70px;">子项2</div>
    <div class="item flex-grow-04" style="width: 50px;">子项3</div>
  </div>
</li>
</ul>
</li>
<li><code>flex-shrink</code>：子项的缩小值，默认值为1，接受非负整数或小数。当所有子项的宽度之后大于容器时，缩小值决定了每个子项根据不足空间缩小的比例。缩小值之和大于等于1时，将不足空间按照缩小值占比缩小；之和小于1时，每个子项直接按不足空间乘以缩小值缩小。
<ul>
<li>缩小值为1、2、2的情况：下面示例中容器宽200px，每个子项100px，因此有100px的不足空间。因为缩小值之和1+2+2=5大于等于1，所以子项1宽度减少100px*1/5=20px，子项2和子项3宽度减少100px*2/5=40px。<div class="container flex-wrap-nowrap" style="width: 200px; height: 50px;">
    <div class="item flex-shrink-1" style="width: 100px;">子项1</div>
    <div class="item flex-shrink-2" style="width: 100px;">子项2</div>
    <div class="item flex-shrink-2" style="width: 100px;">子项3</div>
  </div>
</li>
<li>缩小值为0.1、0.4、0的情况：下面示例中容器宽200px，每个子项100px，因此有100px的不足空间。因为缩小值之和0.1+0.4+0=0.5小于1，所以子项1宽度减少100px*0.1=10px，子项2减少100px*0.4=40px，子项3减少100px*0=0px，共减少50px，还超出50px。<div class="container flex-wrap-nowrap" style="width: 200px; height: 50px;">
  <div class="item flex-shrink-01" style="width: 100px;">子项1</div>
  <div class="item flex-shrink-04" style="width: 100px;">子项2</div>
  <div class="item flex-shrink-0" style="width: 100px;">子项3</div>
</div>
</li>
</ul>
</li>
<li><code>flex-basis</code>：子项初始大小，默认值为auto，由子项自有宽度决定。该元素决定子项在主轴方向上的初始化大小。可接受的值与css中的<code>width</code>一致。这是一个非常有用的属性，因为在计算<code>flex-grow</code>的多余空间或者<code>flex-shrink</code>的不足空间时，都跟每个元素的初始化大小有关系。容器宽度减去子项初始化宽度之和，如果大于0，则为多余空间，小于0，取绝对值为不足空间。所以，即使子项的自有宽度为某一个值时，如果设置<code>flex-basis: 0;</code>，则该子项对于容器来说不占有空间。
<ul>
<li>初始大小为0的情况，下示例中，容器的宽度为300px，每个子项的<code>flex-grow</code>分别为5、2、3，其中子项1设置的宽度为50px，<code>flex-basis</code>设置为0，子项2设置为60px，子项3设置为40px，子项2和子项3不设置<code>flex-basis</code>。所以多余空间为300px-0(子项1的初始宽度)-60px(子项2的初始宽度)-40px(子项3的初始宽度)=200px。然后因为子项的放大值之和5+2+3=10大于等于1，所以子项1增加200px*5/10=100px，子项2增加200px*2/10=40px，子项3增加200px*3/10=60px。所以最终每个子项的宽度为100px。<div class="container flex-wrap-nowrap" style="width: 300px; height: 50px;">
  <div class="item flex-basis-0 flex-grow-5" style="width: 50px;">子项1</div>
  <div class="item flex-shrink-0 flex-grow-2" style="width: 60px;">子项2</div>
  <div class="item flex-shrink-0 flex-grow-3" style="width: 40px;">子项3</div>
</div>
</li>
</ul>
</li>
<li><code>flex</code>：为<code>flex-grow</code>、<code>flex-shrink</code>和<code>flex-basis</code>合并写法。
<ul>
<li><code>flex: 1</code>：这是一个非常有用的简写。其中的1表示<code>flex-grow</code>的值，另外<code>flex-shrink</code>为1，<code>flex-basis</code>为0。如果每个子项都设置成这样，就可以达到设置每个子项均分容器宽度的效果。<div class="container flex-wrap-nowrap" style="width: 300px;">
  <div class="item flex-1">子项1子项1</div>
  <div class="item flex-1">子项2子项2子项2</div>
  <div class="item flex-1">子项3</div>
</div>
</li>
</ul>
</li>
</ul>
<style>
  .container {
    margin: 10px 0;
    display: flex;
    outline: 1px dotted;
    background-color: lightgray;
  }
  .item {
    width: 50px;
    text-align: center;
    color: white;
    font-weight: bold;
  }
  .container .item:nth-child(1) {
    background-color: cornflowerblue;
  }
  .container .item:nth-child(2) {
    background-color: tomato;
  }
  .container .item:nth-child(3) {
    background-color: yellowgreen;
  }
  /* align-items */
  .align-items-stretch {
    align-items: stretch;
  }
  .align-items-flex-start {
    align-items: flex-start;
  }
  .align-items-flex-end {
    align-items: flex-end;
  }
  .align-items-center {
    align-items: center;
  }
  /* align-content */
  .align-content-stretch {
    align-content: stretch;
  }
  .align-content-flex-start {
    align-content: flex-start;
  }
  .align-content-flex-end {
    align-content: flex-end;
  }
  .align-content-center {
    align-content: center;
  }
  .align-content-space-between {
    align-content: space-between;
  }
  .align-content-space-around {
    align-content: space-around;
  }
  .align-content-space-evenly {
    align-content: space-evenly;
  }
  /* flex-wrap */
  .flex-wrap-wrap {
    flex-wrap: wrap;
  }
  .flex-wrap-nowrap {
    flex-wrap: nowrap;
  }
  /* justify-content */
  .justify-content-flex-start {
    justify-content: flex-start;
  }
  .justify-content-flex-end {
    justify-content: flex-end;
  }
  .justify-content-center {
    justify-content: center;
  }
  .justify-content-space-between {
    justify-content: space-between;
  }
  .justify-content-space-around {
    justify-content: space-around;
  }
  .justify-content-space-evenly {
    justify-content: space-evenly;
  }
  /* flex-grow */
  .flex-grow-2 {
    flex-grow: 2;
  }
  .flex-grow-3 {
    flex-grow: 3;
  }
  .flex-grow-5 {
    flex-grow: 5;
  }
  .flex-grow-01 {
    flex-grow: 0.1;
  }
  .flex-grow-02 {
    flex-grow: 0.2;
  }
  .flex-grow-03 {
    flex-grow: 0.3;
  }
  .flex-grow-04 {
    flex-grow: 0.4;
  }
  /* flex-shrink */
  .flex-shrink-0 {
    flex-shrink: 0;
  }
  .flex-shrink-1 {
    flex-shrink: 1;
  }
  .flex-shrink-2 {
    flex-shrink: 2;
  }
  .flex-shrink-3 {
    flex-shrink: 3;
  }
  .flex-shrink-01 {
    flex-shrink: 0.1;
  }
  .flex-shrink-04 {
    flex-shrink: 0.4;
  }
  /* flex-basis */
  .flex-basis-0 {
    flex-basis: 0;
  }
  /* flex-1 */
  .flex-1 {
    flex: 1;
  }
</style>
<h2>参考</h2>
<ul>
<li><a href="https://www.zhangxinxu.com/wordpress/2018/10/display-flex-css3-css/">写给自己看的display: flex布局教程</a></li>
<li><a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flexible_Box_Layout">MDN：CSS 弹性盒子布局
</a></li>
</ul>


</body>
</html>
